#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <linux/fd.h>
#include <sys/mount.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <scsi/scsi_ioctl.h>
#include "debug.h"
#include "public.h"

#define MAXLINE 128

/* U-disk device obtain */
static int find_device(char * name)
{
  char buffer[MAXLINE] = {0};
  FILE * fp;
  char * p = NULL;

  if ((fp = popen("fdisk -l", "r")) == NULL) {
    ac_traces(MSG_LEVEL_ERROR, "popen() error!");
    return -1;
  }

  while (fgets(buffer, sizeof buffer, fp));
  ac_traces(MSG_LEVEL_DEBUG, "buffer=%s\n", buffer);
  if ('\n' == buffer[strlen(buffer) - 1]) {
    buffer[strlen(buffer) - 1] = '\0';
  }
  ac_traces(MSG_LEVEL_DEBUG, "[buffer=%s]\n", buffer);

  p = strstr(buffer, "sd");
  if (p != NULL) {
    ac_traces(MSG_LEVEL_DEBUG, "p=%s\n", p);
    strncpy(name, p, 3);
    ac_traces(MSG_LEVEL_DEBUG, "name=%s\n", name);
    pclose(fp);
    return 1;
  }

  pclose(fp);

  return 0;
}

/*
 * 弹出U盘的代码
 */

static int u_eject(char * name)
{
  int fd = -1;
  char device[32] = {0};
  char cmd[32] = {0};
  int status;
  sg_io_hdr_t io_hdr;
  unsigned char allow_rm_blk[6] = {ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0};
  unsigned char start_stop1_blk[6] = {START_STOP, 0, 0, 0, 1, 0};
  unsigned char start_stop2_blk[6] = {START_STOP, 0, 0, 0, 2, 0};
  unsigned char inq_buff[2] ;
  unsigned char sense_buff[32];

  sprintf(device, "/dev/%s", name);
  ac_traces(MSG_LEVEL_INFO, "device=%s\n", device); 

  sprintf(cmd, "umount -f %s", device);
  xy_popen(cmd);

  if ((fd = open(device, O_RDONLY|O_NONBLOCK)) < 0) {
    printf("open device %s failed!\n", device);
    return -1;
  }

  memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  io_hdr.interface_id = 'S';
  io_hdr.cmd_len = 6;
  io_hdr.mx_sb_len = sizeof(sense_buff);
  io_hdr.dxfer_direction = SG_DXFER_NONE;
  io_hdr.dxfer_len = 0;
  io_hdr.dxferp = inq_buff;
  io_hdr.sbp = sense_buff;
  io_hdr.timeout = 10000;
  io_hdr.cmdp = allow_rm_blk;

  status = ioctl(fd, SG_IO, (void *) &io_hdr);
  if (status < 0) 
    goto out;

  io_hdr.cmdp = start_stop1_blk;
  status = ioctl(fd, SG_IO, (void *) &io_hdr);
  if (status < 0)
    goto out;

  io_hdr.cmdp = start_stop2_blk;
  status = ioctl(fd, SG_IO, (void *) &io_hdr);
  if (status < 0)
    goto out;

  status = ioctl(fd, BLKRRPART);

 out:
  close(fd);

  return 0;
}

void xy_u_eject(void)
{
  char name[4] = {0};
  
  ac_traces(MSG_LEVEL_INFO, "udisk eject");
  if(find_device(name)==1)
    u_eject(name);
}
